<template>
  <div class="canvas-view common-container">
    <div class="canvas-wrap">
      <div class="image-wrap">
        <img class="image-icon" :src="imageIcon" alt="" />
        <canvas
          id="canvas"
          ref="canvasRef"
          class="canvas-dom"
          width="960"
          height="540"
          @click="handleClickCanvas"
        ></canvas>
      </div>
      <div class="opt-wrap">
        <div class="opt-form">
          <t-form :data="formData" layout="inline">
            <t-form-item label="服务启用：" name="name" initial-data="TDesign">
              <t-switch v-model="formData.status" size="large" />
            </t-form-item>
            <t-form-item label="类型：">
              <t-radio-group
                v-model="formData.type"
                name="city"
                :options="TYPE_OPTIONS"
                @change="handleTypeChange"
              ></t-radio-group>
            </t-form-item>
          </t-form>
        </div>
        <div class="opt-btn">
          <div class="btn-wrap">
            <t-button theme="primary" :disabled="canvasDrawStatus === 3 || !formData.status" @click="drawCanvas">
              {{ drawText }}
            </t-button>
            <t-button
              theme="default"
              :disabled="!formData.status || !canvasDataList?.length"
              variant="outline"
              @click="clearData"
            >
              清除
            </t-button>
            <t-button
              theme="default"
              :disabled="!formData.status || !canvasDataList?.length"
              variant="outline"
              @click="resetCanvas"
            >
              重置
            </t-button>
          </div>
          <div class="tip">提示：清晰区域表示算法识别区</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import _ from 'lodash';
import { MessagePlugin } from 'tdesign-vue-next';
import { computed, onMounted, ref } from 'vue';

import imageIcon from '@/assets/images/login-bg-white.png';
import { Point, Points, useCanvas } from '@/hooks/useCanvas';

const TYPE_OPTIONS = [
  { label: '感兴趣区域', value: 1 },
  { label: '非感兴趣区域', value: 2 },
];

const INIT_FORMDATA = { status: false, type: 1 };

const canvasRef = ref<HTMLCanvasElement>();
let ctx: CanvasRenderingContext2D = null;

const {
  initCanvas,
  renderPolygon,
  renderPoint,
  renderLine,
  renderRect,
  clearCanvasRect,
  drawCtxBgColor,
  hollowOutRect,
  isIntersect,
  setGlobalCompositeOperation,
} = useCanvas();

const formData = ref({ ...INIT_FORMDATA });
const canvasDrawStatus = ref(1); // 绘制状态 1.未绘制 2.绘制中 3.已绘制

let canvasDataList: Point[] = [];
let resetData = { canvasList: [] as Point[], formData: { ...INIT_FORMDATA } };

const drawText = computed(() => {
  return canvasDrawStatus.value === 2 ? '停止绘制' : '绘制';
});

const handleTypeChange = () => {
  setCanvasData();
};

// 初始化数据
const initData = () => {
  // 数据请求后得到数据
  const data = { canvasList: [] as Point[], formData: { status: false, type: 1 } };

  canvasDataList = data.canvasList;
  resetData = _.cloneDeep(data);
  ctx = initCanvas('canvas');
  canvasDrawStatus.value = canvasDataList?.length ? 3 : 1;
  setCanvasData();
};

// 初始化画布
const setCanvasData = async () => {
  await clearCanvas();

  setGlobalCompositeOperation(ctx);

  if (formData.value.type === 1) {
    // 感兴趣区域，画框处填充颜色
    // 先画点后画线再填充，因为beginPath的缘故
    canvasDataList.forEach((item) => renderPoint(ctx, item));
    renderPolygon(ctx, canvasDataList);
    drawCtxBgColor(ctx);
  } else {
    // 非感兴趣区域，除画框处填充颜色，用到镂空背景颜色
    renderRect(ctx, { x: 0, y: 0, w: canvasRef.value?.offsetWidth, h: canvasRef.value?.offsetHeight }); // 画布填充颜色
    canvasDataList.forEach((item) => renderPoint(ctx, item));
    renderPolygon(ctx, canvasDataList);
    hollowOutRect(ctx); // 镂空画框处
  }
};

// 清除
const clearCanvas = async () => {
  await clearCanvasRect(ctx, { x: 0, y: 0, w: canvasRef.value?.offsetWidth, h: canvasRef.value?.offsetHeight });

  // 非感兴趣区域要把画布填充颜色
  if (formData.value.type === 2) {
    console.log(111111);
    setGlobalCompositeOperation(ctx);
    renderRect(ctx, { x: 0, y: 0, w: canvasRef.value?.offsetWidth, h: canvasRef.value?.offsetHeight });
  }
};

// 清除数据
const clearData = async () => {
  await clearCanvas();
  canvasDataList = [];
  canvasDrawStatus.value = 1;
};

// 绘制
const drawCanvas = async () => {
  if (canvasDrawStatus.value === 2) {
    if (canvasDataList.length < 3) {
      MessagePlugin.error('请绘制');
      return;
    }

    // 先判断列表最后一个点与第一点连线与其他线段是否相交，不相交才绘制
    const targetData = canvasDataList[0];
    if (isIntersect(targetData, canvasDataList)) {
      MessagePlugin.error('线段相交');
      return;
    }
    await setCanvasData();
  }

  canvasDrawStatus.value += 1;
};

// 重置
const resetCanvas = async () => {
  await clearData();
  canvasDataList = _.cloneDeep(resetData.canvasList);
  formData.value = _.cloneDeep(resetData.formData);
  canvasDrawStatus.value = canvasDataList?.length ? 3 : 1;
  setCanvasData();
};

// 处理点击canvas画布
const handleClickCanvas = (e: any) => {
  // 如果状态未启用或者状态不为绘制中，则不允许绘制
  if (!formData.value.status || canvasDrawStatus.value !== 2) return;

  const { offsetX, offsetY } = e;
  const targetData = { x: offsetX, y: offsetY };

  // 先判断该点连线与其他线段是否相交，不相交才往下走
  if (isIntersect(targetData, canvasDataList)) {
    MessagePlugin.error('线段相交');
    return;
  }

  canvasDataList.push(targetData);

  canvasDataList.forEach((item) => renderPoint(ctx, item));
  if (canvasDataList.length > 1) {
    const arr = canvasDataList.slice(-2) as Points;
    renderLine(ctx, arr);
  }
};

onMounted(() => {
  initData();
});
</script>

<style lang="less" scoped>
.canvas-view {
  background: #fff;

  .canvas-wrap {
    width: 976px;
    padding: 16px;
    box-sizing: border-box;

    .image-wrap {
      width: 960px;
      height: 540px;
      box-sizing: content-box;
      position: relative;

      .image-icon {
        width: 100%;
        height: 100%;
      }

      .canvas-dom {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
      }
    }

    .opt-wrap {
      margin-top: 24px;

      .opt-btn {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-top: 16px;

        .btn-wrap {
          .t-button {
            width: 84px;

            & + .t-button {
              margin-left: 16px;
            }
          }
        }

        .tip {
          color: #fd962d;
          font-size: 12px;
        }
      }
    }
  }
}
</style>
